using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Windows;

namespace MagicKey.Components.FileAccess
{
    class FtpHelper
    {
        public static string MagicKeyDirectory;
        #region Properties

        public string Adress { get; set; }
        public string User { get; set; }
        public string Password { get; set; }

        #endregion

        #region Constructor

        /// <summary>
        /// Initialisiert eine neue Instanz der FTP Helper Klasse
        /// </summary>
        /// <param name="adress">Name oder IP Adresse des Servers</param>
        /// <param name="user">Benutzername</param>
        /// <param name="password">Passwort</param>
        public FtpHelper()
        {
            this.Adress = "ftp.vksm.net";
            this.User = "vksm.net";
            this.Password = "sit_for_password1314";
            MagicKeyDirectory = "magic_key";
            // Check if magic key directory exists
            if (!this.DirectoryExists(MagicKeyDirectory, string.Empty))
            {
                this.CreateFTPDirectory(this.SetUri(string.Empty));
            }
        }

        #endregion

        #region Events

        public delegate void ReceivedFileListCompleteEventhandler();
        public event ReceivedFileListCompleteEventhandler ReceivedFileListComplete;

        #endregion

        /// <summary>
        /// Überprüft ob eine Verbindung zum FTP Server besteht
        /// </summary>
        public bool CheckConnection()
        {
            bool isConnected = false;
            try
            {
                FtpWebRequest.DefaultWebProxy = null;
                FtpWebRequest ftpWebRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + this.Adress + "/"));
                ftpWebRequest.UseBinary = true;
                ftpWebRequest.Credentials = new NetworkCredential(this.User, this.Password);

                //Als Methode muss ListDirectory gewählt werden!
                ftpWebRequest.Method = WebRequestMethods.Ftp.ListDirectory;

                WebResponse webResponse = ftpWebRequest.GetResponse();
                isConnected = true;

                Stream responseStream = webResponse.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                Console.WriteLine(reader.ReadToEnd());

                Console.WriteLine("Connection successfull, status {0}", webResponse.GetResponseStream());
                reader.Close();
            }
            catch (WebException we)
            {
                Console.WriteLine("Connection failed, status {0}", we.GetBaseException().ToString());
            }
            return isConnected;
        }

        private void CreateFTPDirectory(string directoryName)
        {
            WebRequest request = WebRequest.Create(directoryName);
            request.Method = WebRequestMethods.Ftp.MakeDirectory;
            request.Credentials = new NetworkCredential(User, Password);
            using (var resp = (FtpWebResponse)request.GetResponse())
            {
                Console.WriteLine(resp.StatusCode);
            }
        }

        public bool DirectoryExists(string directory, string mainDirectory)
        {
            try
            {
                var list = this.GetFileList(mainDirectory);
                if (list.Contains(directory))
                    return true;
                else
                    return false;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Lädt Dateien auf einen FTP Server
        /// </summary>
        /// <param name="fileInfo"></param>
        public bool UploadFile(FileInfo fileInfo)
        {
            bool isUploaded = false;
            if (fileInfo.Exists)
            {
                try
                {
                    var request = (FtpWebRequest) WebRequest.Create(new Uri(SetUri(fileInfo.Name)));

                    request.UseBinary = true;

                    request.Method = WebRequestMethods.Ftp.UploadFile;

                    request.Credentials = new NetworkCredential(User, Password);

                    byte[] fileContents = File.ReadAllBytes(fileInfo.FullName);

                    request.ContentLength = fileContents.Length;

                    Stream requestStream = request.GetRequestStream();

                    requestStream.Write(fileContents, 0, fileContents.Length);

                    requestStream.Close();

                    var response = (FtpWebResponse) request.GetResponse();

                    response.Close();

                    isUploaded = true;
                }
                catch (WebException we)
                {
                    MessageBox.Show(we.GetBaseException().ToString(), "Upload failed", MessageBoxButton.OK,
                        MessageBoxImage.Error);
                }
            }

            return isUploaded;
        }

        /// <summary>
        /// Liefert eine Liste von Dateien zurück, die sich in einem bestimmten Verzeichnis auf dem Server befinden
        /// </summary>
        /// <returns></returns>
        public List<string> GetFileList(string remoteFolder)
        {
            FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create("ftp://" + Adress + "/" + remoteFolder);
            ftpWebRequest.Method = WebRequestMethods.Ftp.ListDirectory;

            WebResponse webResponse = null;

            ftpWebRequest.Credentials = new NetworkCredential(User, Password);

            try
            {
                webResponse = ftpWebRequest.GetResponse();
            }
            catch (Exception)
            {
                throw;
            }

            List<string> files = new List<string>();

            StreamReader streamReader = new StreamReader(webResponse.GetResponseStream());

            while (!streamReader.EndOfStream)
            {
                files.Add(streamReader.ReadLine());
            }

            streamReader.Close();

            webResponse.Close();

            return files;
        }

        /// <summary>
        /// Liefert eine Liste von Dateien zurück
        /// </summary>
        /// <returns></returns>
        public List<string> GetFileList()
        {
            return this.GetFileList("");
        }

        public string SetUri(string filename)
        {
            return "ftp://" + Adress + "/" + MagicKeyDirectory + "/" + filename;
        }

        /// <summary>
        /// Lädt eine Datei vom FTP Server herunter
        /// </summary>
        public FileInfo DownloadFile(string path)
        {
            FileInfo file = null;
            string localPath;
            try
            {
                string DirectoryPath = "C:/" + MagicKeyDirectory;
                WebClient webClient = new WebClient();

                // Optionally specify an encoding for uploading and downloading strings.
                webClient.Encoding = Encoding.UTF8;

                webClient.Credentials = new NetworkCredential(User, Password);

                byte[] data = webClient.DownloadData(new Uri(path));

                if (!Directory.Exists(DirectoryPath))
                {
                    DirectoryInfo di = Directory.CreateDirectory(DirectoryPath);
                }

                string filename = path.Substring(path.LastIndexOf('/') + 1);
                localPath = DirectoryPath + "/" + filename;
                FileStream fileStream = File.Create(localPath);

                fileStream.Write(data, 0, data.Length);
                fileStream.Close();

                file = new FileInfo(localPath);

            }
            catch (WebException we)
            {
                MessageBox.Show(we.GetBaseException().ToString(), "File not found on the Server", MessageBoxButton.OK, MessageBoxImage.Error);
            }

            return file;
        }

        /// <summary>
        /// Lädt eine Datei vom FTP Server herunter
        /// </summary>
        /// <param name="file"></param>
        /// <param name="destinationFolder"></param>
        /// <param name="destinationFile"></param>
        //public void DownloadFile(FileInfo file)
        //{
        //    this.DownloadFile("", file);
        //}

        /// <summary>
        /// Löscht eine Datei vom FTP Server
        /// </summary>
        /// <param name="remoteFolder">Zielverzeichnis</param>
        /// <param name="fileInfo">Datei</param>
        public bool DeleteFile(Uri file)
        {
            bool fileDeleted = false;
            try
            {
                FtpWebRequest ftpWebRequest = (FtpWebRequest)FtpWebRequest.Create(file);
                ftpWebRequest.UseBinary = true;
                ftpWebRequest.Credentials = new NetworkCredential(User, Password);
                ftpWebRequest.Method = WebRequestMethods.Ftp.DeleteFile;
                ftpWebRequest.Proxy = null;
                ftpWebRequest.KeepAlive = false;
                ftpWebRequest.UsePassive = false;
                ftpWebRequest.GetResponse();

                //               Console.WriteLine("File was deleted,status{0}", ftpWebRequest.GetResponse().ToString());
                fileDeleted = true;
            }
            catch (Exception we)
            {
                MessageBox.Show(we.GetBaseException().ToString(), "File was not deleted", MessageBoxButton.OK, MessageBoxImage.Error);
            }

            return fileDeleted;
        }

    }
}